import cgi
import os
import logging
import datetime

from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
from droidguide_classes import *

def getServiceParameters(service_key):
    results = ServiceParameter.gql("WHERE service_key = :skey",
        skey=service_key)
    return results

def getServiceParameterValue(service_key, service_param_key, droidGuideUser_key):
    results = ServiceParameterValue.gql("WHERE droidGuideUser_key = :dgkey AND service_key = :skey and service_parameter_key= :spKey",
         dgkey=droidGuideUser_key, skey=service_key, spKey=service_param_key)             
    return results

def printServiceWithProperties(self, service):
    service_key = str(service.key())
    service_param_key = self.request.get('service_param_key')
    droidGuideUser_key = self.request.get(DROID_GUIDE_USER_KEY)
    params = getServiceParameters(service_key)

    openEntity(self, ['kind', 'key', 'droidGuideUser_key'], [service.kind(), service.key(), droidGuideUser_key])
    for param in params:
        text = ''
        atributes = ['key', 'name', 'type']
        values = [str(param.key()), param.name, param.type]
        if droidGuideUser_key:
            results = ServiceParameterValue.gql("WHERE droidGuideUser_key = :dgkey AND service_key = :skey and service_parameter_key= :spKey",
               dgkey=droidGuideUser_key, skey=service_key, spKey=str(param.key()))             
            #getServiceParameterValue(service_key, service_param_key, droidGuideUser_key)
            if results:
                serviceParam = results.get()
                if serviceParam and serviceParam.value:
		    attributes.append('valueKey')
		    values.append(atr(serviceParam.key()))
		    text = serviceParam.value
        printXmlElement(self, 'param', attributes, values)
    self.response.out.write('\n</entity>\n')

def printXmlElement(self, elementName, attributes, values, text):
    self.response.out.write('\n<%s ' % elementName)
    n = len(attributes)
    for i in range(1, n):
        printAttribute(self, attribute[i], values[i])
    if text:
        self.response.out.write(' >\n')
        self.response.out.write(text)
	self.response.out.write('</%s >\n' % elementName)
    else:    
        self.response.out.write(' />\n')

#http://localhost:8080/service/process?operation=subscribe&service_key=<String>&droidGuideUser_key=<String>
def subscribeToService(self):
    service_key = self.request.get('service_key')
    droidGuideUser_key = self.request.get(DROID_GUIDE_USER_KEY)
    if droidGuideUser_key and service_key:
        droidGuideUser = getObject(droidGuideUser_key);
        service = getObject(service_key)
        if droidGuideUser and service:
            # check to see if the service is already subscribed to the device
            results = UserToService.gql("WHERE droidGuideUser_key = :dgkey AND service_key = :skey",
               dgkey=droidGuideUser_key, skey=service_key)
            db.delete(results)
            userToService = UserToService()
            userToService.droidGuideUser_key = str(droidGuideUser.key())
            userToService.service_key = str(service.key())
            userToService.put()
            self.response.out.write(userToService.to_xml())

#http://localhost:8080/service/process?operation=createServiceParameter&type=REQUEST&name=flightNumber&service_key=agpkcm9pZGd1aWRlcg0LEgdTZXJ2aWNlGAEM
def createServiceParameter(self):
    type = self.request.get('type')
    name = self.request.get('name')
    service_key = self.request.get('service_key')

    if service_key and name and type:
        serviceParameter = ServiceParameter()
        serviceParameter.type = type
        serviceParameter.name = name
        serviceParameter.service_key = service_key
        serviceParameter.put()
        service = getObject(service_key)
        if service:
            printServiceWithProperties(self, service)

def executeService(self):
    args = self.request.arguments()
    arguments = []
    values = []
    i= 0;
    service_key = ''
    droidGuideUser_key = ''
    for arg in args:
        arguments.append(arg)
        if arg == 'service_key':
            service_key = self.request.get(arg)
        elif arg == 'droidGuideUser_key':
            droidGuideUser_key = self.request.get(arg)
        values.append(self.request.get(arg))
        i  = i + 1

    if service_key:
        service = getObject(service_key)
        if service:
            params = getServiceParameters(service_key)
            for param in params:
                serviceParamKey = str(param.key())
                if param.type == 'RESPONSE':
                   
                    q = ServiceParameterValue.gql("WHERE droidGuideUser_key = :dgkey AND service_key = :skey and service_parameter_key= :spKey",
         dgkey=droidGuideUser_key, skey=service_key, spKey=serviceParamKey) 
                    #getServiceParameterValue(service_key, serviceParamKey, droidGuideUser_key)
                    serviceParamValue = q.get()
                    serviceParamValue.value = str(datetime.datetime.now())
                    serviceParamValue.put()
            printServiceWithProperties(self, service)
        else: 
            self.response.out.write('Service %s not found', service_key)

def listForSubscription(self):
    droidGuideUser_key = self.request.get(DROID_GUIDE_USER_KEY)
    services = Service.all()
    L = []
    L2 = []
    # getting all services
    for service in services:
        serviceKey = str(service.key())
	# getting all user to services for that service
	userToServices = UserToService.gql("WHERE droidGuideUser_key = :dgkey AND service_key = :skey",
               dgkey=droidGuideUser_key, skey=service_key)
	for userToService in userToServices:
	    # if the user is subscribed to this service
	    if userToService.droidGuideUser_key == droidGuideUser_key:
	        L.append(service)

def listSubscribedServices(self):
    droidGuideUser_key = self.request.get(DROID_GUIDE_USER_KEY)
    results = UserToService.gql("WHERE droidGuideUser_key = :1",
	droidGuideUser_key)
    for userToService in results:
        service = db.get(db.Key(userToService.service_key))
        self.response.out.write(service.to_xml())

#http://localhost:8080/service/process?operation=delete&service_key=<String>
def deleteService(self):
    message = ''
    service_key = self.request.get("service_key")
    userToService_key = self.request.get("userToService_key")
    if service_key:
        deleteObject(service_key)
        message = 'service removed from system'
    elif userToService_key:
        deleteObject(userToService_key)
        message = 'user to service removed from system'
    else:
        message = 'no objects have been removed from system'
        
    self.response.out.write(message)

#http://localhost:8080/service/process?operation=delete&=service_key=<String>&droidGuideUser_key=<String>
def unsubscribeToService(self):
      service_key = self.request.get('service_key')
      droidGuideUser_key = self.request.get(DROID_GUIDE_USER_KEY)

      # remove by droid duide user and service key
      if droidGuideUser_key and service_key:
   	  results = UserToService.gql("WHERE droidGuideUser_key = :dgkey AND service_key = :skey",
               dgkey=droidGuideUser_key, skey=service_key)
      for userToService in results:
          userToService.delete()          
      # list the remaining services subscribed to user
      listSubscribedServices(self)

def listServices(self):
      results = Service.all()
      for service in results:
          service_key = str(service.key())
          results = getServiceParameters(service_key)
          printServiceWithProperties(self, service)

def getService(self):
      service_key = self.request.get('service_key')
      service = db.get(db.Key(service_key))
      if service:
          printServiceWithProperties(self, service)

# Creates a new service
def createService(self):
      description = self.request.get('description')
      type = self.request.get('type')
      state = self.request.get('state')
      data = self.request.get('data')      
      if description and type and state:
          service = Service()
          service.description = description
          service.type = type
          service.state = state
          service.data = data
          service.put()          
          self.response.out.write(service.to_xml())
        
def saveServiceParameterValue(self):
    printRequestParams(self)
    key = self.request.get('key')
    value = self.request.get('value')
    if key:
        serviceParamValue = db.get(db.Key(key))
        if serviceParamValue:
            serviceParamValue.value = value;
            serviceParamValue.datetime = datetime.datetime.now()
            serviceParamValue.put()
            self.response.out.write(serviceParamValue.to_xml())
    else:
        self.response.out.write('Parameter missing')
    
def createServiceParameterValue(self):
    service_key = self.request.get('service_key')
    droidGuideUser_key = self.request.get(DROID_GUIDE_USER_KEY)
    service_param_key = self.request.get('service_param_key')
    checkRequiredParams(self, ['service_key', DROID_GUIDE_USER_KEY, 'service_param_key']);
        
    q = getServiceParameterValue(service_key, service_param_key, droidGuideUser_key)
    serviceParamValue = q.get()
    if serviceParamValue:
        serviceParamValue.value = value;
        serviceParamValue.datetime = datetime.datetime.now()
        serviceParamValue.put()
    else: 
        serviceParamValue = ServiceParameterValue()
        serviceParamValue.service_parameter_key = service_param_key 
        serviceParamValue.service_key = service_key
        serviceParamValue.droidGuideUser_key = droidGuideUser_key
        serviceParamValue.value = value
        serviceParamValue.datetime = datetime.datetime.now()
        serviceParamValue.put()
    self.response.out.write(serviceParamValue.to_xml())
    
class Process(webapp.RequestHandler):
  def get(self):
    operation = self.request.get("operation")
    entity = self.request.get("entity")

    startDroidGuideMessage(self)
    
    # creates a new service
    # http://droidguide.appspot.com/service/process?operation=create&description=weather%20data&type=weather&state=AVAILABLE&data=Ouro%20Preto
    if operation == 'create':
        createService(self)        

    #http://localhost:8080/service/process?operation=delete&userToService_key=agpkcm9pZGd1aWRlchQLEg1Vc2VyVG9TZXJ2aWNlGIwBDA
    elif operation == 'delete':
        deleteService(self)
    
    elif operation == 'list':
        listServices(self)
    
    # list subscribed services
    elif operation == 'listSubscribed':
        listSubscribedServices(self)

    # subscribes to a service
    elif operation == 'subscribe':
        subscribeToService(self)

    #unsubscribes to a service
    elif operation == 'unsubscribe':
        unsubscribeToService(self)

    elif operation == 'createServiceParameter':
        createServiceParameter(self)

    elif operation == 'getService':
        getService(self)
    
    elif operation == 'saveServiceParamValue':
        saveServiceParameterValue(self)
        
    elif operation == 'createServiceParamValue':
        createServiceParameterValue(self)

    elif operation == 'listServiceParamValue':
        listObjects(ServiceParameterValue, self)
        
    elif operation == 'execute':
        executeService(self)

    else:
        self.response.out.write('unsupported operation')
    
    finishDroidGuideMessage(self)

application = webapp.WSGIApplication([('/service/process', Process)], debug=True)

def main():
  run_wsgi_app(application)

if __name__ == '__main__':
  main()
